#include <stdio.h>
#include <stdlib.h>
#include <string.h>


#include "stm32f10x.h"
#include "tick.h"
#include "hardware.h"
#include "SensorChannels.h"
#include "FrequencySensor.h"


#undef TRACE_LEVEL
#undef TRACE_TITLE
#undef TRACE_TITLE
#define TRACE_LEVEL	TRACE_LEVEL_DEBUG
#define TRACE_NAME  TRACE_NAME_DISABLE
#define TRACE_TITLE "FREQ"
#include "trace.h"


int OpenFrequencySensor(int channel, const SensorChannelHw_t *Hw) {
	GPIO_InitTypeDef GPIO_InitStructure;
	TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
	TIM_ICInitTypeDef  TIM_ICInitStructure;
	
	uint32_t TimerCounterClock = 72000000;
	uint32_t TimerFrequency = 1000000;
	
	// Only Channel 0 can be used for TIM-ETR
	if(channel != 2) {
		return -1;
	}
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
	
	// Set IOA as input floating
	GPIO_InitStructure.GPIO_Pin = Hw->DataLineA.PinMask;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(Hw->DataLineA.Port, &GPIO_InitStructure);
	
	// Set IOB as input pullup
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
	GPIO_InitStructure.GPIO_Pin = Hw->DataLineB.PinMask;
	GPIO_Init(Hw->DataLineB.Port, &GPIO_InitStructure);
	
	// Disable pullup power
	GPIO_InitStructure.GPIO_Pin = Hw->PowerPullupCtrl.PinMask;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
	GPIO_Init(Hw->PowerPullupCtrl.Port, &GPIO_InitStructure);
	
	TIM_DeInit(TIM2);
	// Config timer as ext-clock source conter
	TIM_TimeBaseStructure.TIM_Period = 0xFFFF;
	TIM_TimeBaseStructure.TIM_Prescaler = 0;
	TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
	TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);  // Time base configuration

	TIM_ETRClockMode2Config(TIM2, TIM_ExtTRGPSC_OFF, TIM_ExtTRGPolarity_NonInverted, 0);

	TIM_SetCounter(TIM2, 0);
	TIM_Cmd(TIM2, ENABLE);
	// TIM_GetCounter(TIM2);

#ifdef INPUT_CAPTURE_MODE
	TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;
	TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
	TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
	TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
	TIM_ICInitStructure.TIM_ICFilter = 0x0;

	TIM_ICInit(TIM2, &TIM_ICInitStructure);

	/* TIM enable counter */
	TIM_Cmd(TIM2, ENABLE);

	/* Enable the CC2 Interrupt Request */
	TIM_ITConfig(TIM2, TIM_IT_CC2, ENABLE);
#endif
	return 0;
}

// Used RX3 to test 
static void TestIOInit() {
	GPIO_InitTypeDef GPIO_InitStructure;
	
	GPIO_InitStructure.GPIO_Pin = USART3_RXD_PIN;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(USART3_PORT, &GPIO_InitStructure);
}

__IO uint16_t IC3ReadValue1 = 0, IC3ReadValue2 = 0;
__IO uint16_t CaptureNumber = 0;
__IO uint32_t Capture = 0;
__IO uint32_t TIM2Freq = 0;
void TIM2InputCaptureModeInterruptHandler() {
	if(CaptureNumber == 0)
    {
      /* Get the Input Capture value */
      IC3ReadValue1 = TIM_GetCapture2(TIM2);
      CaptureNumber = 1;
    }
    else if(CaptureNumber == 1)
    {
      /* Get the Input Capture value */
      IC3ReadValue2 = TIM_GetCapture2(TIM2); 
      
      /* Capture computation */
      if (IC3ReadValue2 > IC3ReadValue1)
      {
        Capture = (IC3ReadValue2 - IC3ReadValue1); 
      }
      else
      {
        Capture = ((0xFFFF - IC3ReadValue1) + IC3ReadValue2); 
      }
      /* Frequency computation */ 
      TIM2Freq = (uint32_t) SystemCoreClock / Capture;
      CaptureNumber = 0;
	  TRACE_DEBUG("freq=%d", TIM2Freq);
  }
}

void TestFreqOutput(uint32 freq) {
	GPIO_InitTypeDef GPIO_InitStructure;
	TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
	TIM_OCInitTypeDef  TIM_OCInitStructure;
	uint16_t PrescalerValue = 0;
	uint16_t CCR4_Val = 333;
	
	uint32_t TimerCounterClock = 24000000;
	uint32_t TimerFrequency = freq;
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
	
	/* -----------------------------------------------------------------------
    TIM3 Configuration: generate 4 PWM signals with 4 different duty cycles:
    The TIM3CLK frequency is set to SystemCoreClock (Hz), to get TIM3 counter
    clock at 24 MHz the Prescaler is computed as following:
     - Prescaler = (TIM3CLK / TIM3 counter clock) - 1
    SystemCoreClock is set to 72 MHz for Low-density, Medium-density, High-density
    and Connectivity line devices and to 24 MHz for Low-Density Value line and
    Medium-Density Value line devices

    The TIM3 is running at 36 KHz: TIM3 Frequency = TIM3 counter clock/(ARR + 1)
                                                  = 24 MHz / 666 = 36 KHz
    TIM3 Channel1 duty cycle = (TIM3_CCR1/ TIM3_ARR)* 100 = 50%
    TIM3 Channel2 duty cycle = (TIM3_CCR2/ TIM3_ARR)* 100 = 37.5%
    TIM3 Channel3 duty cycle = (TIM3_CCR3/ TIM3_ARR)* 100 = 25%
    TIM3 Channel4 duty cycle = (TIM3_CCR4/ TIM3_ARR)* 100 = 12.5%
  ----------------------------------------------------------------------- */
  
	// We used channel1 as pwm output
	GPIO_InitStructure.GPIO_Pin = CH1_IOB_PIN;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

	GPIO_Init(CH1_IOB_PORT, &GPIO_InitStructure);
	
	PrescalerValue = (uint16_t) (SystemCoreClock / TimerCounterClock) - 1;
	/* Time base configuration */
	TIM_TimeBaseStructure.TIM_Period = TimerCounterClock / TimerFrequency - 1;	// 665;
	TIM_TimeBaseStructure.TIM_Prescaler = PrescalerValue;
	TIM_TimeBaseStructure.TIM_ClockDivision = 0;
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;

	TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
	
	/* PWM1 Mode configuration: Channel4 */
	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
	TIM_OCInitStructure.TIM_Pulse = TimerCounterClock / TimerFrequency / 2;
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;

	TIM_OC4Init(TIM3, &TIM_OCInitStructure);

	TIM_OC4PreloadConfig(TIM3, TIM_OCPreload_Enable);
	
	TIM_ARRPreloadConfig(TIM3, ENABLE);

	/* TIM3 enable counter */
	TIM_Cmd(TIM3, ENABLE);
}

int FrequencySensorMain() {
// 	uint32_t count;
// 	int i;
	
// 	OpenFrequencySensor(2, &channelHwInfo[2]);
	// TestIOInit();
	TestFreqOutput(300000);
// 	while (1) {
// 		TIM_SetCounter(TIM2, 0);
// 		// TIM_Cmd(TIM2, ENABLE);
// 		delay_ms(10);
// 		count = TIM_GetCounter(TIM2);
// 		TRACE_DEBUG_WP("\r");
// 		TRACE_DEBUG_WP("COUNT=%d, FREQ=%0.3fKHz", count, (float)count / (float)10.0);
// 	}
}
